package vns.client.presenter;

import java.util.ArrayList;

import vns.client.VNSmartUI;
import vns.client.event.AccountEvent;
import vns.client.event.AccountEventManager;
import vns.client.helper.RPCCall;
import vns.client.service.AccountOAuthServiceAsync;
import vns.client.service.ObjectService;
import vns.client.service.ObjectServiceAsync;
import vns.client.service.ObjectTypeService;
import vns.client.service.ObjectTypeServiceAsync;
import vns.client.view.AccountAccessButton;
import vns.client.view.AccountUI;
import vns.shared.AccountData;
import vns.shared.ObjectDTO;
import vns.shared.ObjectTypeDTO;
import vns.shared.SupperAdminDTO;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;

public class AccountPresenter implements Presenter {

	@Override
	public void go(HasWidgets container) {
		container.clear();
		container.add(display.asWidget());
		this.dialogBox = (DialogBox) container;
		init();
	}

	public interface Display {
		Widget asWidget();

		Button getLoginButton();

		AccountAccessButton getAccountAccessButton();

		AccountData getAccountData();

		HTML getH1();

		HTML getH2();

		HTML getHNote();

		void setAccountData(AccountData accountData);

		void setLoginState(int loginState);
	}

	private final Display display;
	private final SimpleEventBus eventBus;
	private final AccountOAuthServiceAsync rpcService;
	private final ObjectTypeServiceAsync rpcObjectType = GWT
			.create(ObjectTypeService.class);
	private final ObjectServiceAsync rpcObject = GWT
			.create(ObjectService.class);

	private DialogBox dialogBox;
	private final SupperAdminDTO adminDTO;

	/*
	 * Public method
	 */

	public AccountPresenter(AccountUI view, SimpleEventBus eventBus,
			AccountOAuthServiceAsync model, SupperAdminDTO adminDTO) {
		this.display = view;
		this.eventBus = eventBus;
		this.rpcService = model;
		this.adminDTO = adminDTO;
		setup();
	}

	/*
	 * Private method
	 */
	private void init() {
		final String currentUrl = Window.Location.getPath()
				+ Window.Location.getQueryString() + "#" + History.getToken();
		new RPCCall<AccountData>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Không load được tài khoản");
			}

			@Override
			public void onSuccess(AccountData result) {
				processLoginData(result);
			}

			@Override
			protected void callService(AsyncCallback<AccountData> cb) {
				rpcService.getLoginData(currentUrl, cb);
			}
		}.retry(3);
	}

	private void authorize() {

		new RPCCall<ArrayList<ObjectTypeDTO>>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Không load được kiểu danh sách!"
						+ caught.toString());
			}

			@Override
			public void onSuccess(ArrayList<ObjectTypeDTO> result) {
				int i = 0;
				for (final ObjectTypeDTO otDTO : result) {
					if (otDTO.getIsuser()) {

						// ****************************************
						// *

						new RPCCall<ArrayList<ObjectDTO>>() {

							@Override
							public void onFailure(Throwable caught) {
								Window.alert("Không load được kiểu danh sách!"
										+ caught.toString());
							}

							@Override
							public void onSuccess(ArrayList<ObjectDTO> result) {
								for (ObjectDTO oDTO : result) {
									if (display.getAccountData()
											.getGoogleEmail()
											.equalsIgnoreCase(oDTO.getMain())) {
										display.getAccountData()
												.setGoogleIsRegistered(true);
										// Window.alert("Email này đã dc dang ki:"
										// + oDTO.getMain());
										display.setLoginState(AccountEventManager.LOGGEDIN);
										drawLoggedIn();
										break;
									}
								}

							}

							@Override
							protected void callService(
									AsyncCallback<ArrayList<ObjectDTO>> cb) {
								rpcObject.Loadall(otDTO, cb);
							}
						}.retry(3);

						// *
						// ****************************************

						if (display.getAccountData().isGoogleIsRegistered())
							break;
					}
					i++;
				}
				if (i >= result.size()
						&& !display.getAccountData().isGoogleIsRegistered()) {
					drawUnregistered();
				}
			}

			@Override
			protected void callService(
					AsyncCallback<ArrayList<ObjectTypeDTO>> cb) {
				rpcObjectType.Loadall(cb);
			}
		}.retry(3);

	}

	private void setup() {
		display.getAccountAccessButton().addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				AccountAccessButton b = (AccountAccessButton) event.getSource();
				int e = b.getChangeEvent();
				if (e == AccountEventManager.OAUTHTOKEN_RETRIEVED) {
					// getSomeBlogData();
					displayLogin();
				}
			}
		});

		display.getLoginButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				eventBus.fireEvent(new AccountEvent("login"));
			}
		});

	}

	protected void displayLogin() {
		display.getHNote().setHTML("Truy cập thành công!");
		VNSmartUI.get().setAccountData(display.getAccountData());
		display.getLoginButton().setVisible(true);
	}

	private void getSomeBlogData() {
		rpcService.getBlogList(new AsyncCallback<String>() {
			public void onSuccess(String s) {
				processBlogData(s);
			}

			public void onFailure(Throwable caught) {
				// TODO
			}
		});
	}

	protected void processBlogData(String s) {
		display.getAccountAccessButton().setVisible(false);
		display.getHNote().setHTML("My Blogs: <br/><br/>" + s);
	}

	private void processLoginData(AccountData data) {
		display.setAccountData(data);
		if (display.getAccountData() == null
				|| display.getAccountData().getGoogleLoggedIn() == false) {
			display.setLoginState(AccountEventManager.LOGGEDOUT);
			drawLoggedOut();
		} else if (display.getAccountData().getGoogleEmail()
				.equalsIgnoreCase(adminDTO.getEmail())) {
			dialogBox.hide();
			VNSmartUI.get().setAccountData(display.getAccountData());
			eventBus.fireEvent(new AccountEvent("adminLogin"));
		} else {
			authorize();
		}
		dialogBox.show();
		dialogBox.center();
	}

	private void drawLoggedOut() {
		String url = display.getAccountData().getGoogleLoginUrl();
		String signIn = "<a href=\"" + url
				+ "\"> [Đăng nhập vào tài khoản Google] </a>&nbsp;&nbsp;";
		String create = "<a href=\"" + url + "\"> [Tạo tài khoản mới] </a>";
		display.getH1().setHTML(signIn);
		display.getH2().setHTML(create);
		display.getAccountAccessButton().getBAskForAccess().setEnabled(false);
	}

	protected void drawLoggedIn() {
		String url = display.getAccountData().getGoogleLogoutUrl();
		String nick = "<a>" + display.getAccountData().getGoogleNickNotNull()
				+ "</a>&nbsp;&nbsp;";
		String logOut = "<a href=\"" + url + "\">[Thoát]</a>";
		display.getH1().setHTML(nick);
		display.getH2().setHTML(logOut);
		display.getAccountAccessButton().getBAskForAccess().setEnabled(true);
		// chi dung cho test
		// begin
		displayLogin();
		// end
	}

	protected void drawUnregistered() {
		String url = display.getAccountData().getGoogleLogoutUrl();
		String nick = "<a>" + display.getAccountData().getGoogleNickNotNull()
				+ "</a>&nbsp;&nbsp;";
		String logOut = "<a href=\"" + url + "\">[Thoát]</a>";
		display.getH1().setHTML(nick);
		display.getH2().setHTML(logOut);
		display.getHNote().setHTML("Xin lỗi, bạn chưa được đăng kí!");

		display.getAccountAccessButton().getBAskForAccess().setEnabled(false);

	}
}
